package org.smile.db.sql;

import org.smile.collection.ResultMap;
import org.smile.db.JdbcTemplate;
import org.smile.db.PageModel;
import org.smile.db.handler.LikeBeanRowHandler;
import org.smile.db.handler.OneFieldRowHandler;
import org.smile.db.handler.RowHandler;
import org.smile.reflect.ClassTypeUtils;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 查询
 * @author 胡真山
 *
 */
public class Query {
	/**
	 * 结果集处理
	 */
	private RowHandler handler;
	/**
	 * 限制查询条数
	 */
	private int limit=0;

	private int offset=0;
	/**
	 * 查询语句
	 */
	private String sql;
	/**
	 * 用来保存参数值
	 */
	private final Map parameters =new QueryParams();

	JdbcTemplate template;

	public Query(JdbcTemplate template){
		this.template=template;
	}

	public Query limit(int limit){
		this.limit=limit;
		return this;
	}

	public Query parameter(String name,Object value){
		parameters.put(name,value);
		return this;
	}
	/**
	 * 设置参数
	 * @param index
	 * @param val
	 */
	public Query parameter(int index,Object val){
		parameters.put(index,val);
		return this;
	}

	private BoundSql boundSql(){
		return new NamedBoundSql(sql, this.parameters);
	}

	private BoundSql topBoundSql(int top){
		String limitSql=template.getDialect().getDialectPage(sql).getTopSql(top);
		return new NamedBoundSql(limitSql, this.parameters);
	}

	public Query handler(RowHandler handler) {
		this.handler = handler;
		return this;
	}

	public Query sql(String sql) {
		this.sql = sql;
		return this;
	}

	public Integer forInt(){
		return template.queryFirst(boundSql(), OneFieldRowHandler.INTEGER);
	}

	public Double forDouble(){
		return template.queryFirst(boundSql(), OneFieldRowHandler.DOUBLE);
	}

	public Long forLong(){
		return template.queryFirst(boundSql(), OneFieldRowHandler.LONG);
	}

	public String forString(){
		return template.queryFirst(boundSql(), OneFieldRowHandler.STRING);
	}

	/**
	 * 返回map类型
	 * @return
	 */
	public ResultMap forMap(){
		return template.queryForMap(boundSql());
	}

	/**
	 * 返回类型
	 * @param type
	 */
	public void resultType(Class type){
		if(ClassTypeUtils.isOneFieldType(type)){
			this.handler=new OneFieldRowHandler(type);
		}else{
			this.handler=new LikeBeanRowHandler(type);
		}
	}

	/**
	 * 第一行数据返回map类型
	 * @return
	 */
	public ResultMap firstMap(){
		return this.template.queryFirst(boundSql(),RowHandler.RESULT_SET_MAP);
	}

	/**
	 * 返回单字段内容
	 * @param type
	 * @param <T>
	 * @return
	 */
	public <T> T forField(Class<T> type){
		return this.template.queryFirst(boundSql(), OneFieldRowHandler.instance(type));
	}

	/**
	 * 返回一个列表
	 * @param type
	 * @param <T> 列表中封装的类型
	 * @return
	 */
	public <T> List<T> list(Class<T> type){
		if(ClassTypeUtils.isOneFieldType(type)){
			return this.template.query(boundSql(),new OneFieldRowHandler(type));
		}
		return this.template.query(boundSql(),new LikeBeanRowHandler(type));
	}
	/**
	 * @return
	 */
	private RowHandler buildHandler(){
		return this.handler==null?RowHandler.RESULT_SET_MAP:this.handler;
	}
	/**
	 * @param handler
	 * @param <E>
	 * @return
	 */
	protected  <E> List<E> queryList(RowHandler handler){
		if(this.limit>0) {
			String limitSql=template.getDialect().getDialectPage(sql).getLimitSql(this.offset,this.limit);
			NamedBoundSql boundSql= new NamedBoundSql(limitSql, this.parameters);
			return this.template.query(boundSql, handler);
		}else {
			return this.template.query(boundSql(), handler);
		}
	}
	/**
	 * 返回列表查询
	 * @param <T>
	 * @return
	 */
	public <T> List<T> list(){
		return queryList(buildHandler());
	}

	/**
	 * 前多少行
	 * @param top
	 * @param <T>
	 * @return
	 */
	public <T> List<T> top(int top){
		return this.template.query(topBoundSql(top), buildHandler());
	}

	/**
	 * 分页查询
	 * @param page
	 * @param size
	 * @param <E>
	 * @return
	 */
	public <E> PageModel page(int page,int size){
		return this.template.queryPageSql(buildHandler(),boundSql(),page,size);
	}

	/**
	 * 返回字符串列表
	 * @return
	 */
	public List<String> listString(){
		return  queryList(OneFieldRowHandler.STRING);
	}

	public static class QueryParams extends TreeMap{

	}

}
